package cn.i7baozh.starter.gateway.loadbalancer.component;

import cn.i7baozh.starter.gateway.loadbalancer.dto.InstanceInfo;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 从远程配置中获取当前可用的分组信息
 *
 * @author : baoqi.zhang
 * @date :   2022/5/17 19:35
 */
@RefreshScope
@Component
public class AvailableGroupNacosConfigComponent {

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * 远程配置中可用的服务组
     */
    @Value("${gateway.available.group:}")
    private String availableGroup;

    /**
     * 服务的权重、健康信息
     * host_port:{"weight":2,"healthy":true}
     */
    @Value("${gateway.instance.info:}")
    private String instanceInfo;

    /**
     * 随机获取可用服务的组信息
     *
     * @return
     */
    public String getCurrentAvailableServiceGroup() {
        if (StringUtils.isNoneBlank(availableGroup)) {
            List<String> availableGroups = Lists.newArrayList(Splitter.on(",").split(availableGroup));
            int index = ThreadLocalRandom.current().nextInt(availableGroups.size());
            return availableGroups.get(index);
        }
        return null;
    }

    /**
     * 获取主机额外配置信息
     * @param host
     * @param port
     * @return
     */
    public InstanceInfo getInstanceInfo(String host, int port) {
        if (StringUtils.isNoneBlank(instanceInfo)) {
            try {
                List<InstanceInfo> instanceRemoteInfo = objectMapper.readValue(instanceInfo, new TypeReference<List<InstanceInfo>>() {
                });

                return instanceRemoteInfo.stream()
                        .filter(e -> host.equals(e.getHost()) && port == e.getPort())
                        .findFirst().map(e -> InstanceInfo
                                .builder()
                                .host(e.getHost())
                                .port(e.getPort())
                                .healthy(e.getHealthy())
                                .weight(e.getWeight())
                                .build()).orElse(null);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
